package org.netty.framework.core;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.netty.framework.core.codec.Header;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ClassUtils;

/**
 * 根据类加载器是否能够加载启动类,启动netty server
 * @author chenfanglin
 * @date 2018年10月8日下午5:07:43
 */
public class NettyServerApplication {

	private static final String HTTP_SERVER_CLASS_NAME = "org.netty.framework.httpserver.HttpServer";

	private static final String TCP_SERVER_CLASS_NAME = "org.netty.framework.tcpserver.TcpServer";
	
	private static final String WEB_SOCKET_SERVER_CLASS_NAME = "org.netty.framework.websocket.WebSocketServer";

	private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(3);

	/**
	 * 判断当前类加载器能够加载相应的启动类,启动相应的服务,可以同时启动多个服务
	 */
	public static void start() {
		start(Header.class);
	}
	
	public static void start(Class<?> headerClazz) {
		if (ClassUtils.isPresent(HTTP_SERVER_CLASS_NAME, null)) {
			EXECUTOR_SERVICE.submit(new StartTask(HTTP_SERVER_CLASS_NAME));
		}
		if (ClassUtils.isPresent(TCP_SERVER_CLASS_NAME, null)) {
			EXECUTOR_SERVICE.submit(new StartTask(TCP_SERVER_CLASS_NAME, headerClazz));
		}
		if (ClassUtils.isPresent(WEB_SOCKET_SERVER_CLASS_NAME, null)) {
			EXECUTOR_SERVICE.submit(new StartTask(WEB_SOCKET_SERVER_CLASS_NAME));
		}
	}

	/**
	 * 启动线程
	 */
	private static class StartTask extends Thread {

		private String className;
		
		private Class<?> headerClazz;

		private StartTask(String className) {
			this(className, null);
		}
		private StartTask(String className, Class<?> headerClazz) {
			this.className = className;
			this.headerClazz = headerClazz;
			super.setName("netty-server-start");
		}

		@Override
		public void run() {
			startServer(className, headerClazz);
		}

	}

	/**
	 * 实例化启动类,调用start()方法启动服务
	 * @param className
	 */
	private static void startServer(String className, Class<?> headerClazz) {
		try {
			Class<?> clazz = Class.forName(className);
			if (headerClazz != null) {
				AbstractNettyServer nettyServer = (AbstractNettyServer) BeanUtils.instantiateClass(clazz);
				nettyServer.start(headerClazz);
			} else {
				NettyServer nettyServer = (NettyServer) BeanUtils.instantiateClass(clazz);
				nettyServer.start();
			}
			
		} catch (Exception e) {
			throw new UnsupportedOperationException("start netty server fail.");
		}

	}
}
